package com.ynkbny.util;


import com.ynkbny.entity.AppQuartz;
import com.ynkbny.service.BaseJob;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Properties;

import static org.quartz.DateBuilder.futureDate;


@Component
public class QuartzUtil {

    Logger logger = LoggerFactory.getLogger(QuartzUtil.class);

    @Resource
    private DateUnit dateUnit;

    //加入Qulifier注解，通过名称注入bean
    @Resource
    @Qualifier("Scheduler")
    private Scheduler scheduler;

    @Resource
    @Qualifier("dataProperties")
    private Properties properties;


    public String addJob(AppQuartz appQuartz) throws Exception  {
        if ("".equals(appQuartz.getJobGroup()) || "".equals(appQuartz.getJobName()) || "".equals(appQuartz.getJobClassName()) || "".equals(appQuartz.getCronExpression())) {
            return "没有接收到参数,请检查";
        }
        if (appQuartz.getTimeType() == null) {
            return addCronJob(appQuartz);
        }
        return addSimpleJob(appQuartz);
    }


    /**
     * 添加任务
     * @param appQuartz 任务调度实体类
     * @return
     * @throws Exception
     */
    public String addCronJob(AppQuartz appQuartz) throws Exception {

        // 启动调度器
        scheduler.start();
        String className =  appQuartz.getJobClassName().trim();
        String [] classNames = className.split("\\.");
        //构建job信息
        JobDetail jobDetail = JobBuilder.newJob(getClass(className).getClass())
                .withDescription(appQuartz.getDescription())
                .withIdentity(appQuartz.getJobName(), appQuartz.getJobGroup())
                .build();

        //表达式调度构建器(即任务执行的时间)
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(appQuartz.getCronExpression());
        //按新的cronExpression表达式构建一个新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger()
                .withDescription(appQuartz.getDescription())
                .withIdentity(classNames[classNames.length-1], classNames[classNames.length-2])
                .withSchedule(scheduleBuilder)
                .build();

        //传递参数
        if(appQuartz.getInvokeParam()!=null && !"".equals(appQuartz.getInvokeParam())) {
            trigger.getJobDataMap().put("invokeParam",appQuartz.getInvokeParam());
        }
        try {
            scheduler.scheduleJob(jobDetail, trigger);
            return "success";
        } catch (SchedulerException e) {
            logger.error("创建定时任务失败", e);
            return e.getMessage();
        }
    }


    /**
     * 暂停任务
     * @param jobName
     * @param jobGroupName
     * @throws Exception
     */
    public void jobPause(String jobName, String jobGroupName) throws Exception {
        scheduler.pauseJob(JobKey.jobKey(jobName, jobGroupName));
    }


    /**
     * 恢复任务
     * @param jobName
     * @param jobGroupName
     * @throws SchedulerException
     */
    public void jobResume(String jobName, String jobGroupName) throws SchedulerException {
        scheduler.resumeJob(JobKey.jobKey(jobName, jobGroupName));
        //scheduler.pauseJob(JobKey.jobKey(jobName,jobGroupName));
    }


    /**
     * 删除任务,先暂停任务，再进行删除,否则会出现异常
     * @param jobName
     * @param jobGroupName
     * @throws Exception
     */
    public void jobDelete(String jobName, String jobGroupName) throws Exception {
        scheduler.pauseTrigger(TriggerKey.triggerKey(jobName, jobGroupName));
        scheduler.unscheduleJob(TriggerKey.triggerKey(jobName, jobGroupName));
        scheduler.deleteJob(JobKey.jobKey(jobName, jobGroupName));
    }


    /**
     * 修改任务
     * @param appQuartz
     * @throws Exception
     */
    public void modifyJob(AppQuartz appQuartz) throws Exception {
        jobreschedule(appQuartz.getTriggerName(), appQuartz.getTriggerGroup(), appQuartz.getCronExpression());
    }


    /**
     * 修改任务
     * @param triggerName
     * @param triggerGroup
     * @param cronExpression
     * @throws Exception
     */
    public void jobreschedule(String triggerName, String triggerGroup, String cronExpression) throws Exception {
        TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroup);
        // 表达式调度构建器
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

        // 按新的cronExpression表达式重新构建trigger
        CronTrigger triggerNew = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();

        // 按新的trigger重新设置job执行
        scheduler.rescheduleJob(triggerKey, triggerNew);

    }

    /**
     * 添加普通时间任务
     * @param appQuartz
     * @return
     * @throws Exception
     */
    public String addSimpleJob(AppQuartz appQuartz) throws Exception {

        // 启动调度器
        scheduler.start();
        String className =  appQuartz.getJobClassName().trim();
        String [] classNames = className.split("\\.");
        //构建job信息
        JobDetail jobDetail = JobBuilder.newJob(getClass(className).getClass())
                .withDescription(appQuartz.getDescription())
                .withIdentity(appQuartz.getJobName(), appQuartz.getJobGroup())
                .build();

        DateBuilder.IntervalUnit verDate = dateUnit.verification(appQuartz.getTimeType());
        SimpleTrigger simpleTrigger = (SimpleTrigger) TriggerBuilder.newTrigger()
                .withDescription(appQuartz.getDescription())
                .withIdentity(classNames[classNames.length-1], classNames[classNames.length-2])
                .startAt(futureDate(Integer.parseInt(appQuartz.getCronExpression()), verDate))
                .forJob(appQuartz.getJobClassName(), appQuartz.getJobGroup())
                .build();

        //传递参数
        if(appQuartz.getInvokeParam()!=null && !"".equals(appQuartz.getInvokeParam())) {
            simpleTrigger.getJobDataMap().put("invokeParam",appQuartz.getInvokeParam());
        }
        try {
            scheduler.scheduleJob(jobDetail, simpleTrigger);
            return "success";
        } catch (SchedulerException e) {
            logger.error("创建定时任务失败", e);
            return e.getMessage();
        }
    }
    public Boolean checkJob (AppQuartz appQuartz) throws SchedulerException {
        JobKey jobKey = new JobKey(appQuartz.getJobName(), appQuartz.getJobGroup());
        if(scheduler.checkExists(jobKey)){

            return true;
        }
        return false;
    }


    /**
     * 根据类名称，通过反射得到该类，然后创建一个BaseJob的实例。
     * 由于自己的Job类都实现了BaseJob，
     * 所以这里不需要我们手动去判断。这里涉及到了一些java多态调用的机制
     *
     * @param classname
     * @return
     * @throws Exception
     */
    public static BaseJob getClass(String classname) throws Exception {
        Class<?> class1 = Class.forName(classname);
        return (BaseJob) class1.newInstance();
    }



}
